import sys
import re
from poplib import POP3
from smtplib import SMTP
from email import message_from_bytes
from email.mime.application import MIMEApplication
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from base64 import decodebytes
from quopri import decodestring

# mye.py bind xxx@xx.xx password
# mye.py bind status
# mye.py list [count]
# mye.py retr id
# mye.py send xxx@xx.xx contentfilename [attachmentfilename]

def main():
    argc = len(sys.argv)
    if argc == 4 and sys.argv[1] == 'bind':
        bind(sys.argv[2],sys.argv[3])
    elif argc == 3 and sys.argv[1] == 'bind' and sys.argv[2] == 'status':
        bind_status()
    elif argc == 2 and sys.argv[1] == 'list':
        _list()
    elif argc == 3 and sys.argv[1] == 'list' and sys.argv[2].isdigit():
        _list(int(sys.argv[2]))
    elif argc == 3 and sys.argv[1] == 'retr' and sys.argv[2].isdigit():
        retr(int(sys.argv[2]))
    elif argc == 4 and sys.argv[1] == 'send':
        send(sys.argv[2],sys.argv[3]) 
    elif argc == 5 and sys.argv[1] == 'send':
        send(sys.argv[2],sys.argv[3],sys.argv[4])
    else:
        print("Unable to parse command!") 

def bind(email_addr,password):
    server_name = "pop." + email_addr[email_addr.index('@')+1:]
    pop3 = POP3(server_name)
    pop3.user(email_addr[:email_addr.index('@')])
    pop3.pass_(password)
    pop3.quit()
    PATH = sys.argv[0][:sys.argv[0].rfind('\\')]
    f = open(PATH+'\\mye.conf','w')
    f.write(email_addr+'\n'+password)
    f.close
    print('bind success!')

def bind_status():
    tag,email_addr,password = get_info_from_file()
    if tag:
        print("Email Address: ",email_addr)
        print("Password: ",password)
    else:
        print("You didn't bind before!")

def decode_string(string):
    if string is None:
        return '空'
    ss = string.__str__().split(" ")   # qq系统退信subject直接用utf-8原文,这时 string 是一个email.header.Header
    if len(ss) > 1:
        ret = ""
        for i in range(len(ss)): 
            ret += decode_string(ss[i])
        return ret
    lis = string.__str__().split('?')
    if len(lis) == 1:
        return string.__str__()
    debytes = bytes(0)
    if lis[2].upper() == 'B':
        try:
            debytes = decodebytes(bytes(lis[3],'ascii'))
        except:
            return '[base64解码失败]' + lis[3]
    else:
        try:
            debytes = decodestring(bytes(lis[3],'ascii'))  # quopri
        except:
            return '[quopri解码失败]' + lis[3]
    return str(debytes,lis[1])

def _list(c = -1):
    tag,email_addr,password = get_info_from_file()
    if tag:
        server_name = "pop." + email_addr[email_addr.index('@')+1:]
        pop3 = POP3(server_name)
        pop3.user(email_addr[:email_addr.index('@')])
        pop3.pass_(password)
        count,size = pop3.stat()
        index = count - c
        if index > count or index < 0:
            index = 0
        print("ID\tFrom\tTo\tDate\tSubject\t\tEmail Count = %d" % count)
        for i in range(count,index,-1):
            resp,lines,octets = pop3.top(i,0)
            tmsg = message_from_bytes(bytes([13,10]).join(lines))
            print("%d\t%s\t%s\t%s\t%s\n"%((i,)+tuple([decode_string(tmsg.get(k)) for k in ['From','To','Date','Subject']]) ) )
        pop3.quit()
    else:
        print("You didn't bind before!")

def retr(id):
    tag,email_addr,password = get_info_from_file()
    if tag:
        server_name = "pop." + email_addr[email_addr.index('@')+1:]
        pop3 = POP3(server_name)
        pop3.user(email_addr[:email_addr.index('@')])
        pop3.pass_(password)
        print('receiving...')
        resp,lines,octets = pop3.retr(id)
        # b = bytes(line[0])
        # for i in range(1,line.__len__()):  # 这里运行比较费时间,用bytes([13,10]).join(lines)快很多
        #     b += bytes([13,10]) + line[i]
        msg = message_from_bytes(bytes([13,10]).join(lines))
        subj = re.sub('[\\/*:?\"<>|]','_',decode_string(msg.get('Subject')))
        print('邮件标题: ',subj)
        if msg.is_multipart():
            for part in msg.walk():                
                if part.get_content_type() == 'text/plain':                   
                    data = part.get_payload(decode=True)
                    f = open(subj+".plain",'wb')
                    f.write(data)
                    f.close()
                    print('save ',subj+'.plain success!')
                elif part.get_content_type() == 'text/html':                
                    data = part.get_payload(decode=True)
                    f = open(subj+".html","wb")
                    f.write(data)
                    f.close()
                    print('save ',subj+'.html success!')
                elif part.get_filename() is not None:  # attachment
                    data = part.get_payload(decode=True)
                    filename = decode_string( part.get_filename() )      
                    f = open(filename,'wb')
                    f.write(data)    
                    f.close()
                    print('save ',filename,' success!')
        else:
            data = msg.get_payload(decode=True)                        
            f = open(subj+".html",'wb')
            f.write(data)
            f.close()
            print('save ',subj+'.html success!')
        pop3.quit()
    else:
        print("You didn't bind before!")

def send(dest_email_addr,content_file,attachment_file = ''):
    tag,email_addr,password = get_info_from_file()
    if tag:
        smtp = SMTP('smtp.'+email_addr[email_addr.index('@')+1:])
        smtp.login(email_addr[:email_addr.index('@')],password)
        print('Building...')
        mp = MIMEMultipart('alternative')
        try:
            f = open(content_file,'r',encoding='utf-8')
            cont = f.read()
            f.close()
        except UnicodeDecodeError:
            f = open(content_file,'r',encoding='gb18030')
            cont = f.read()
            f.close()
        text = MIMEText(cont)        # cont的charset默认都是utf-8
        mp.attach(text)  
        if attachment_file != '':
            f = open(attachment_file,'rb')
            data = f.read()
            f.close()
            atta = MIMEApplication(data)
            atta.add_header('Content-Disposition','attachment',filename=attachment_file)
            mp.attach(atta) 
        mp['To'] = dest_email_addr
        mp['Subject'] = content_file
        print('Sending...')   
        errs = smtp.sendmail(email_addr,dest_email_addr,mp.as_string())
        if errs.__len__() == 0:
            print('Send success!')
        else:
            print(errs)
        smtp.quit()        
    else:
        print("You didnn't bind before!")

def get_info_from_file():
    PATH = sys.argv[0][:sys.argv[0].rfind('\\')]
    try:
        f = open(PATH+"\\mye.conf",'r')
        email_addr,password = f.readlines()
        f.close()
        return (True,email_addr.strip(),password)
    except FileNotFoundError:
        return (False,'','')

if __name__ == "__main__":
    main()